﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Threading;
using Microsoft.DirectX.AudioVideoPlayback;
using SongSharp.Domain.Objects;
using System.Diagnostics;
using SongSharp.Logging;

namespace SongSharp.Domain.Playing
{
    internal class ChannelAgent
    {
        internal struct ChannelObject
        {
            internal bool IsValid { get; set; }
            internal Audio Audio { get; set; }
            internal BackgroundWorker AudioDelayManager { get; set; }
        }

        private const int MAX_CHANNELS = 8;
        internal const int SWITCH_DELAY_MS = 600;
        internal const int HIGH_CONCENTRATION_TIME_INTERVAL_MS = 2000;
        // Defines the maximum volume of DirectX Audio
        internal const int DIRECTX_MAX_VOLUME = 0;
        // Defines the minimum volume that has been tested
        // Standard minimum volume: -10000
        internal const int DIRECTX_MIN_VOLUME = -2000;

        private int m_volume;
        private int m_channelIndex;
        private ChannelObject[] Channels { get; set; }

        public ChannelAgent()
        {
            Channels = new ChannelObject[MAX_CHANNELS];
        }

        internal int CurrentIndex
        {
            get
            {
                if (m_channelIndex == MAX_CHANNELS)
                    m_channelIndex = 0;
                return m_channelIndex;
            }
            set
            {
                m_channelIndex = value;
            }
        }

        internal ChannelObject CurrentChannel
        {
            get
            {
                return Channels[CurrentIndex];
            }
        }

        /// <summary>
        /// Accepts a volume range between 0 and 100
        /// </summary>
        internal int Volume
        {
            get
            {
                return m_volume;
            }
            set
            {
                m_volume = value * ((Math.Abs(DIRECTX_MAX_VOLUME) + Math.Abs(DIRECTX_MIN_VOLUME))/100) + DIRECTX_MIN_VOLUME;
                if (CurrentChannel.IsValid)
                {
                    CurrentChannel.Audio.Volume = m_volume;
                }
            }
        }

        internal ChannelObject Get(int channel)
        {
            return Channels[channel];
        }

        internal int GetNext(int channel)
        {
            if (++channel == MAX_CHANNELS)
                return 0;
            return channel;
        }

        internal int GetPrevious(int channel)
        {
            if (--channel < 0)
                return (int)MAX_CHANNELS - 1;
            return channel;
        }

        internal int Create(BackgroundWorker audioManager, Audio audio)
        {
            CurrentIndex++;

            Clean();

            Channels[CurrentIndex].Audio = audio;
            Channels[CurrentIndex].Audio.Volume = m_volume;
            Channels[CurrentIndex].AudioDelayManager = audioManager;
            Channels[CurrentIndex].IsValid = true;
            //Logger.Log("Created new channel with index: " + CurrentIndex, Logger.LogAction.Playback);
            return CurrentIndex;
        }

        internal void Clean()
        {
            Clean(CurrentIndex);
        }

        internal void Clean(int index)
        {
            if (index < 0)
                index = (int)MAX_CHANNELS - 1;
            if (Channels[index].IsValid)
            {
                //Logger.Log("Cleaned channel with index: " + index, Logger.LogAction.Playback);
                Channels[index].Audio.Stop();
                Channels[index].AudioDelayManager.CancelAsync();
                Channels[index].IsValid = false;
                
                Channels[index].Audio.Dispose();
                Channels[index].Audio = null;
                Channels[index].AudioDelayManager.Dispose();
                Channels[index].AudioDelayManager = null;
            }
        }
    }
}
